package com.tengju.data.infrastructure.repository;

import com.google.common.collect.Lists;
import com.tengju.data.domain.model.clickhouse.DwsUserDominationTeamParent;
import com.tengju.data.domain.model.clickhouse.star.*;
import com.tengju.data.domain.model.user.*;
import com.tengju.data.domain.shared.IdObject;
import com.tengju.data.infrastructure.persistence.mybatis.dataobject.*;
import com.tengju.data.infrastructure.persistence.mybatis.mapper.clickhouse.user.DwdUserDominationRelationMapAllMapper;
import com.tengju.data.infrastructure.persistence.mybatis.mapper.clickhouse.user.UserDominationDetailMapper;
import com.tengju.data.infrastructure.repository.clickhouse.convert.StarConvert;
import com.tengju.data.infrastructure.repository.convert.DominationDetailConvert;
import com.tengju.user.domain.model.sign.StarAuditStatEnum;
import com.tengju.user.domain.model.sign.StarSignStepEnum;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Repository
public class DominationDetailRepositoryImpl implements DominationDetailRepository {

    @Resource
    UserDominationDetailMapper userDominationDetailMapper;

    @Resource
    DwdUserDominationRelationMapAllMapper dwdUserDominationRelationMapAllMapper;

    @Override
    public DominationDetail getByIdCode(UserIdCode idCode) {
        List<DwdUserDominationDetailDO> userDominationDetailDOList =
                userDominationDetailMapper.queryByIdCodes(List.of(idCode.getValue()));
        DwdUserDominationDetailDO userDominationDetailDO = null;
        if (!CollectionUtils.isEmpty(userDominationDetailDOList)) {
            userDominationDetailDO = userDominationDetailDOList.get(0);
        }
        return DominationDetailConvert.convertToModel(userDominationDetailDO);
    }

    @Override
    public Integer customCount(List<UserIdCode> idCodes, List<StarLevelEnum> starLevel, DominationLevelEnum dominationLevel, UserIdCode leaderId, IsDirect isDirect) {

        if (CollectionUtils.isEmpty(starLevel)) {
            return 0;
        }

        List<Integer> starLevelVal = starLevel.stream()
                .map(StarLevelEnum::getCode).collect(Collectors.toList());

        List<Long> idCodeLongs = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(idCodes)) {
            idCodeLongs = idCodes.stream().map(IdObject::getValue).collect(Collectors.toList());
        }
        return userDominationDetailMapper
                .countCustom(idCodeLongs, starLevelVal, dominationLevel.getVal(), leaderId.getValue(), isDirect.getVal());
    }

    @Override
    public List<UserIdCode> getIdCodeCustom(List<UserIdCode> idCodes, List<StarLevelEnum> starLevel, DominationLevelEnum dominationLevel, UserIdCode leaderId, IsDirect isDirect) {

        if (CollectionUtils.isEmpty(starLevel)) {
            return Lists.newArrayList();
        }

        List<Integer> starLevelVal = starLevel.stream()
                .map(StarLevelEnum::getCode).collect(Collectors.toList());

        List<Long> idCodeLongs = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(idCodes)) {
            idCodeLongs = idCodes.stream().map(IdObject::getValue).collect(Collectors.toList());
        }
        List<Long> customIdCodes = userDominationDetailMapper
                .getCustomIdCode(idCodeLongs, starLevelVal, dominationLevel.getVal(), leaderId.getValue(), isDirect.getVal());
        return customIdCodes.stream().map(UserIdCode::new).collect(Collectors.toList());
    }

    @Override
    public List<DominationDetail> customList(List<UserIdCode> idCodes, List<StarLevelEnum> starLevel, DominationLevelEnum dominationLevel, UserIdCode leaderId, IsDirect isDirect, DominationMemberSortType sortType, Integer offset, Integer limit) {

        List<Long> idCodeLongs = idCodes.stream().map(IdObject::getValue).collect(Collectors.toList());
        List<Integer> starLevelValList = starLevel.stream().map(StarLevelEnum::getCode).collect(Collectors.toList());

        List<DwdUserDominationDetailDO> userDominationDetailDOList = userDominationDetailMapper.queryByPage(
                idCodeLongs, starLevelValList, dominationLevel.getVal(), leaderId.getValue(), isDirect.getVal(),
                sortType.getSql(), offset, limit);

        return userDominationDetailDOList.stream()
                .map(DominationDetailConvert::convertToModel).collect(Collectors.toList());
    }

    @Override
    public DominationMemberNew countNewMemberCurrentMonth(UserIdCode dominationIdCode, DominationLevelEnum dominationLevel, List<StarLevelEnum> starLevelList, LocalDateTime from, LocalDateTime to) {

        Date fromDate = Date.from(from.atZone(ZoneId.systemDefault()).toInstant());
        Date toDate = Date.from(to.atZone(ZoneId.systemDefault()).toInstant());

        List<DominationTeamCountDO> dominationTeamCountDOList =
                dwdUserDominationRelationMapAllMapper
                        .queryNewMember(dominationIdCode.getValue(), dominationLevel.getVal(), null, fromDate, toDate);
        return DominationDetailConvert.convertToMemberNewModel(dominationTeamCountDOList);
    }

    @Override
    public DominationMemberNew countNewMemberCurrentMonthByIdCodes(List<UserIdCode> dominationIdCodes, DominationLevelEnum dominationLevel, LocalDateTime from, LocalDateTime to) {

        Date fromDate = Date.from(from.atZone(ZoneId.systemDefault()).toInstant());
        Date toDate = Date.from(to.atZone(ZoneId.systemDefault()).toInstant());

        List<Long> dominationIdCodesVal = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(dominationIdCodes)) {
            dominationIdCodesVal = dominationIdCodes.stream().map(IdObject::getValue).collect(Collectors.toList());
        }

        List<DominationTeamCountDO> dominationTeamCountDOList =
                dwdUserDominationRelationMapAllMapper
                        .queryNewMemberByIdCodes(dominationIdCodesVal, dominationLevel.getVal(), null, fromDate, toDate);
        return DominationDetailConvert.convertToMemberNewModel(dominationTeamCountDOList);
    }

    @Override
    public List<DominationIdCodeMemberNew> countNewMemberCurrentMonthByDominationIdCodes(
            List<UserIdCode> dominationIdCodes,
            DominationLevelEnum dominationLevel,
            List<String> visitDates,
            Date fromDate,
            Date toDate) {

        List<Long> dominationIdCodesVal = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(dominationIdCodes)) {
            dominationIdCodesVal = dominationIdCodes.stream().map(IdObject::getValue).collect(Collectors.toList());
        }

        List<DominationIdCodeTeamCountDO> dominationIdCodeTeamCountDOList = dwdUserDominationRelationMapAllMapper.
                queryNewMemberByDominationIdCodes(dominationIdCodesVal, dominationLevel.getVal(), null, visitDates, fromDate, toDate);
        List<DominationIdCodeTeamCountDO> dealerDominationIdCodeTeamCountDOList = dwdUserDominationRelationMapAllMapper.
                queryDealerNewMemberByDominationIdCodes(dominationIdCodesVal, dominationLevel.getVal(), null, visitDates, fromDate, toDate);
        return DominationDetailConvert.convertToIdCodeMemberNewModel(dominationIdCodeTeamCountDOList, dealerDominationIdCodeTeamCountDOList);
    }

    @Override
    public List<UpgradingDetail> queryNewMemberCurrentMonth(UserIdCode dominationIdCode, DominationLevelEnum dominationLevel, List<StarLevelEnum> starLevelList, LocalDateTime from, LocalDateTime to, int offset, int limit) {

        Date fromDate = Date.from(from.atZone(ZoneId.systemDefault()).toInstant());
        Date toDate = Date.from(to.atZone(ZoneId.systemDefault()).toInstant());

        List<Integer> starLevelValList = null;
        if (!CollectionUtils.isEmpty(starLevelList)) {
            starLevelValList = starLevelList.stream().map(StarLevelEnum::getCode).collect(Collectors.toList());
        }

        List<UpgradingDetailDO> upgradingDetailDOList = dwdUserDominationRelationMapAllMapper
                .queryNewMemberDetail(dominationIdCode.getValue(), dominationLevel.getVal(), starLevelValList, fromDate, toDate, offset, limit);
        if (CollectionUtils.isEmpty(upgradingDetailDOList)) {
            return Lists.newArrayList();
        }
        return upgradingDetailDOList.stream().map(DominationDetailConvert::convertToModel).collect(Collectors.toList());
    }

    @Override
    public DominationUpComing countUpComingMemberByIdCodes(List<UserIdCode> idCodes, DominationLevelEnum dominationLevel) {

        if (CollectionUtils.isEmpty(idCodes)) {
            return DominationUpComing.zero();
        }

        List<Long> idCodesVal = idCodes.stream().map(IdObject::getValue).collect(Collectors.toList());

        List<DominationTeamCountDO> dominationTeamCountDOList = dwdUserDominationRelationMapAllMapper
                .dominationStarChangeRecordNumByIdCodes(idCodesVal, dominationLevel.getVal(), StarChangeNoticeType.UP_SOON.getType());

        return DominationDetailConvert.convertToUpcomingModel(dominationTeamCountDOList);
    }

    @Override
    public DominationUpComing countUpComingMemberByCurrentStarLevel(UserIdCode idCode, DominationLevelEnum dominationLevel, List<StarLevelEnum> starLevelList) {

        List<Integer> starLevelValList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(starLevelList)) {
            starLevelValList = starLevelList.stream().map(StarLevelEnum::getCode).collect(Collectors.toList());
        }

        List<DominationTeamCountDO> dominationTeamCountDOList = dwdUserDominationRelationMapAllMapper
                .dominationStarChangeRecordNumByBeforeStarLevel(idCode.getValue(),
                        dominationLevel.getVal(), StarChangeNoticeType.UP_SOON.getType(), starLevelValList);
        return DominationDetailConvert.convertToUpcomingModel(dominationTeamCountDOList);
    }

    @Override
    public List<StarChangeNoticeRecord> queryUpComingMemberByCurrentStarLevel(UserIdCode idCode, DominationLevelEnum dominationLevel, List<StarLevelEnum> starLevelList, int offset, int limit) {

        List<Integer> starLevelValList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(starLevelList)) {
            starLevelValList = starLevelList.stream().map(StarLevelEnum::getCode).collect(Collectors.toList());
        }

        List<StarChangeNoticeRecordDO> starChangeNoticeRecordDOList = dwdUserDominationRelationMapAllMapper.dominationStarChangeRecordDetailByBeforeStarLevel(idCode.getValue(),
                dominationLevel.getVal(), StarChangeNoticeType.UP_SOON.getType(), starLevelValList, offset, limit);

        return starChangeNoticeRecordDOList.stream()
                .map(StarConvert::toStarChangeNoticeRecordDO)
                .collect(Collectors.toList());
    }

    @Override
    public DominationUpComing countUpComingMemberByUpComingStarLevel(UserIdCode idCode, DominationLevelEnum dominationLevel, List<StarLevelEnum> targetStarLevelList, List<StarLevelEnum> currentStarLevelList) {
        List<Integer> targetStarLevelValList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(targetStarLevelList)) {
            targetStarLevelValList = targetStarLevelList.stream().map(StarLevelEnum::getCode).collect(Collectors.toList());
        }

        List<Integer> currentStarLevelValList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(targetStarLevelList)) {
            currentStarLevelValList = currentStarLevelList.stream().map(StarLevelEnum::getCode).collect(Collectors.toList());
        }

        List<DominationTeamCountDO> dominationTeamCountDOList = dwdUserDominationRelationMapAllMapper
                .dominationStarChangeRecordNumByUpComingStarLevel(idCode.getValue(),
                        dominationLevel.getVal(), StarChangeNoticeType.UP_SOON.getType(),
                        targetStarLevelValList, currentStarLevelValList);
        return DominationDetailConvert.convertToUpcomingModel(dominationTeamCountDOList);
    }

    @Override
    public List<StarChangeNoticeRecord> queryUpComingMemberByUpComingStarLevel(UserIdCode idCode, DominationLevelEnum dominationLevel, List<StarLevelEnum> targetStarLevelList, List<StarLevelEnum> currentStarLevelList, int offset, int limit) {
        List<Integer> targetStarLevelValList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(targetStarLevelList)) {
            targetStarLevelValList = targetStarLevelList.stream().map(StarLevelEnum::getCode).collect(Collectors.toList());
        }
        List<Integer> currentStarLevelValList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(targetStarLevelList)) {
            currentStarLevelValList = currentStarLevelList.stream().map(StarLevelEnum::getCode).collect(Collectors.toList());
        }
        List<StarChangeNoticeRecordDO> starChangeNoticeRecordDOList = dwdUserDominationRelationMapAllMapper.dominationStarChangeRecordDetailByUpComingStarLevel(idCode.getValue(),
                dominationLevel.getVal(), StarChangeNoticeType.UP_SOON.getType(), targetStarLevelValList, currentStarLevelValList, offset, limit);

        return starChangeNoticeRecordDOList.stream()
                .map(StarConvert::toStarChangeNoticeRecordDO)
                .collect(Collectors.toList());
    }

    @Override
    public DominationSigningMember countSigningMemberByIdCodesDominationLevel(List<UserIdCode> idCodes, DominationLevelEnum dominationLevel) {

        if (CollectionUtils.isEmpty(idCodes)) {
            return DominationSigningMember.zero();
        }

        List<Long> idCodesVal = idCodes.stream().map(IdObject::getValue).collect(Collectors.toList());

        List<DominationTeamCountDO> dominationTeamCountDOList = dwdUserDominationRelationMapAllMapper.dominationTeamSignCountByStepsNotAuditStats(idCodesVal, dominationLevel.getVal(),
                List.of(StarSignStepEnum.SEND_ALREADY.getStep(), StarSignStepEnum.SURVEY_ALREADY.getStep(),
                        StarSignStepEnum.ACCOUNT_ALREADY.getStep(), StarSignStepEnum.AUDIT_ALREADY.getStep(),
                        StarSignStepEnum.EXAM_ALREADY.getStep()), List.of(StarAuditStatEnum.DENY_AUDIT.getCode()));

        return DominationDetailConvert.convertToSigningMemberModel(dominationTeamCountDOList);
    }


    @Override
    public boolean isDominationMember(UserIdCode idCode, UserIdCode dominationIdCode, DominationLevelEnum dominationLevel) {

        Integer count = dwdUserDominationRelationMapAllMapper.isDominationMember(idCode.getValue(),
                dominationIdCode.getValue(),
                dominationLevel.getVal());

        if (count != null && count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public List<DwsUserDominationTeamParent> getUserDominationTeamParent() {
        List<DwdUserDominationTeamParentDO> dwdUserDominationTeamParentDOList = dwdUserDominationRelationMapAllMapper.queryUserDominationTeamParent();
        return DominationDetailConvert.convert(dwdUserDominationTeamParentDOList);
    }

    @Override
    public List<DwsUserDominationTeamParent> getEecDominationTeamParent() {
        List<DwdUserDominationTeamParentDO> dwdUserDominationTeamParentDOList = dwdUserDominationRelationMapAllMapper.queryEecDominationTeamParent();
        return DominationDetailConvert.convert(dwdUserDominationTeamParentDOList);
    }

    @Override
    public List<DwsUserDominationTeamParent> getUserDominationTeamParentByDominationIdCodeList(List<UserIdCode> dominationIdCodeList) {
        if (CollectionUtils.isEmpty(dominationIdCodeList)) {
            return new ArrayList<>();
        }
        List<Long> dominationIdCodeValList = dominationIdCodeList.stream()
                .map(UserIdCode::getValue)
                .collect(Collectors.toList());
        List<DwdUserDominationTeamParentDO> dwdUserDominationTeamParentDOList = dwdUserDominationRelationMapAllMapper.queryUserDominationTeamParentByDominationIdCodeList(dominationIdCodeValList);
        return DominationDetailConvert.convert(dwdUserDominationTeamParentDOList);
    }

    @Override
    public List<DwsUserDominationTeamParent> getEecDominationTeamParentByDominationIdCodeList(List<UserIdCode> dominationIdCodeList) {
        if (CollectionUtils.isEmpty(dominationIdCodeList)) {
            return new ArrayList<>();
        }
        List<Long> dominationIdCodeValList = dominationIdCodeList.stream()
                .map(UserIdCode::getValue)
                .collect(Collectors.toList());
        List<DwdUserDominationTeamParentDO> dwdUserDominationTeamParentDOList = dwdUserDominationRelationMapAllMapper.queryEecDominationTeamParentByDominationIdCodeList(dominationIdCodeValList);
        return DominationDetailConvert.convert(dwdUserDominationTeamParentDOList);
    }

    @Override
    public List<DwsUserDominationTeamParent> getUserDominationTeamParentByDominationIdCode(UserIdCode dominationIdCode) {
        if (dominationIdCode == null) {
            return new ArrayList<>();
        }
        List<DwdUserDominationTeamParentDO> dwdUserDominationTeamParentDOList = dwdUserDominationRelationMapAllMapper.queryUserDominationTeamParentByDominationIdCode(dominationIdCode.getValue());
        return DominationDetailConvert.convert(dwdUserDominationTeamParentDOList);
    }

}
